Mybatis笔记

Mybatis开始

SQL语句输出方式

1.在全局配置文件中,配置标签

    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

2.使用log4j等工具,进行输出

mapper中传递参数方式

#{}和${}的区别 #{}表示占位符的方式拼接sql语句 占位符为"?" ${}表示拼接字符串的方式拼接sql语句 ${}很少用

<select id="selAll" resultType="com.bjsxt.pojo.People" parameterType="int">
        select *from People where id=#{0} //传入参数为 的时候 使用索引 占位符选择0位置第一个参数   当传入参数只有一个的时候,#{}大括号中内容可以位任意字符
        select *from People where id=#{param1}//param+数字表示第几个参数,从1开始
        select *from People where id=#{0}//此时不使用索引  单纯的id=0
</select>
<select id="selAll" resultType="com.bjsxt.pojo.People" parameterType="com.bjsxt.pojo.People">
        select *from People where id=#{id}
        select *from People where id=${id}//若使用拼接字符串方式,则需要传入为对象,mybatis自动在传入的对象中寻找对应名字的getset方法来获取值
</select>
<select id="selAll" resultType="com.bjsxt.pojo.People" parameterType="java.util.Map">
        select *from People where id=#{key} //#{}中填写map的key
</select>

全局配置文件解释

1.1 <transactionManager/> type 属性可取值 1.1.1 JDBC,事务管理使用 JDBC 原生事务管理方式 1.1.2 MANAGED 把事务管理转交给其他容器,如交给Spring进行管理.原生JDBC 事务 setAutoMapping(false); 1.2 <dataSouce/>type 属性 1.2.1 POOLED 使用数据库连接池 1.2.2 UNPOOLED 不实用数据库连接池,和直接使用 JDBC 一样 1.2.3 JNDI :java 命名目录接口技术.

例子:

<configuration>
    <!-- default引用environment的id,当前所使用的环境 -->
    <environments default="default">
        <!-- 声明可以使用的环境 -->
        <environment id="default">
            <!-- 使用原生JDBC事务 -->
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
                <property name="username" value="root"/>
                <property name="password" value="yu752949273"/>
            </dataSource>
        </environment>
    </environments>

 

绝对路径

如果是请求转发 / 表示项目根目录(WebContent) 其他重定向,<img/> <script/>,<style/>,location.href 等/都表示服务器根目录(tomcat/webapps 文件夹) 如果客户端请求的控制器,控制器转发到JSP后,jsp中如果使用相对路径,需要按照控制器的路径去找其他资源. 尽量使用绝对路径 避免相对路径与控制器路径冲突的问题

 

mybatis与ibatis的区别

版本

2.x为ibatis 3.x为mybatis

全局配置文件中

ibatis中使用sqlMap元素,mybatis中使用mappers元素 ibatis中根元素是sqlMapConfig,mybatis中是configuration settings中属性配置不同

ibatis中为

<settings 属性1="属性值1" 属性2="属性值2"  属性x="属性值x"/>

mybatis中为

<settings>

<setting name="属性1" value="属性值1"/>

<setting name="属性2" value="属性值2"/>

<setting name="属性x" value="属性值x"/>

</settings>

映射文件中

ibatis中使用sqlMap元素,mybatis中使用mapper元素

resultMap

当返回值类型为resultMap时,需要在mapper中编写resultMap与实体类中的属性向映射,其中 一对一association 一对多,多对多collection

<association property="" column="" select=""></association>  <!--property为映射实体类中属性 column为数据库中属性列 select为子查询id-->
<collection property="" column="" ofType="" select=""></collection> <!--property为映射实体类中属性 column为数据库中属性列 select为子查询id  ofType为另一对多的实体类-->

动态sql

标签

<where>   <set>   <if test="a!=null and a!=''">   <trim>   <bind>   <choose><when><otherwise>    <sql><include>   <foreach>

<where>标签

先去掉条件的第一个and 然后添加where 当where中的条件不存在时 where标签也不存在

<select id="selByAccinAccout" resultType="log">
    select * from log
        <where>
            <if test="accin!=null and accin!=''"> 
                and accin=#{accin}
            </if>
            <if test="accout!=null and accout!=''">
                and accout=#{accout}
            </if>
        </where>
</select>

<set>标签

先去掉条件的最后一个逗号 然后在最前面添加set 当set中的条件不存在时 set标签也不存在

<update id="upd" parameterType="log" >
update log
    <set>
        id=#{id},
        <if test="accIn!=null and accIn!=''">
            accin=#{accIn},
        </if>
        <if test="accOut!=null and accOut!=''">
            accout=#{accOut},
        </if>
    </set>
where id=#{id}
</update>

<if>标签

若不满足条件则该字句不存在 test等于的字符串中,若条件为多个,则用and或or连接 不是&或|

<if test="accin!=null and accin!=''">
and accin=#{accin}
</if>

<trim>标签

prefix 在前面添加内容 prefixOverrides 去掉前面内容 suffix 在后面添加内容 suffixOverrieds 去掉后面内容 执行顺序为 先去掉内容 再添加内容

<update id="upd" parameterType="log">
    update log
        <trim prefix="set" suffixOverrides=",">
            a=a,
        </trim>
    where id=100
</update>

<bind>标签

为传递的变量拼接字符

<bind name="aaa" value="'$'+aaa"/>

<choose><when><otherwise>标签

    <choose>
        <when test="a!=null">
        </when>
    </choose>
    <choose>
        <when test="b!=null">
        </when>
    </choose>

只要有一个成立,其他都不执行. 若存在多个能够成立的,则只执行成立的第一个

choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql。

<sql><include>标签

sql片段 复用 <sql id="a"></sql> <include refid="a"></include>

<foreach>标签

<foreach collection="" item="" index="" open="" close="" separator="">

</foreach>

foreach 也就是遍历迭代,在SQL中通常用在 in 这个关键词的后面

foreach元素的属性主要有 item,index,collection,open,separator,close。

分别代表:

item表示集合中每一个元素进行迭代时的别名,
index用于表示在迭代过程中,每次迭代到的位置,
open表示该语句以什么开始,
separator表示在每次进行迭代之间以什么符号作为分隔 符,
close表示以什么结束
 
代码片段:
<select id="selectByIds" resultType="com.txw.pojo.User">
        select * from user where id in
        <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
</select>

而最为重要的就是collection属性了,既然是迭代就表示传入的参数是多个,这时候传入的参数就有以下几种可能:

1. 传入的参数为list的时候

 对应的Dao中的Mapper文件是:

public List<User> selectByIds(List<Integer> ids);
 
xml文件代码片段:
<select id="selectByIds" resultType="com.txw.pojo.User">
        select * from user where id in
        <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
</select>
2. 传入的参数为Array的时候

对应的Dao中的Mapper文件是:

public List<User> selectByIds(int[] ids);

xml文件代码片段: 

<select id="selectByIds" resultType="com.txw.pojo.User">
        select * from user where id in
        <foreach collection="array" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>
 
3. 传入的参数为Map的时候
对应的Dao中的Mapper文件是:

public List<User> selectByIds(Map<String, Object> params);

xml文件代码片段: 

<select id="selectByIds" resultType="com.txw.pojo.User">
        select * from user where  id in
        <foreach collection="ids" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>
 
map的时候需要注意的是:collection的值“ids”是存储在map中的key(比如:map.put("ids",ids));尤其需要注意;

 

ThreadLocal线程容器

给线程绑定一个Object容器,若线程状态不变则可以随时取出,若线程发生改变,则无法取出.

final ThreadLocal<String> threadLocal = new ThreadLocal<>();
threadLocal.set("测试");
new Thread(){
    public void run() {
    String result = threadLocal.get();
    System.out.println("结果:"+result);//线程改变无法取出
    };
}.start();
String result = threadLocal.get();
System.out.println("结果:"+result);//可以取出

主要用于同一Servlet线程,静态加载SqlSessionFactory

工具类:

import java.io.IOException;
import java.io.InputStream;
​
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
​
public class MyBatisUtil {
    //factory实例化的过程是一个比较耗费性能的过程.
    //保证有且只有一个factory
    private static SqlSessionFactory factory;
    private static ThreadLocal<SqlSession> tl = new ThreadLocal<>();
    static{
        try {
            InputStream is = Resources.getResourceAsStream("mybatis.xml");
            factory = new SqlSessionFactoryBuilder().build(is);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /**
     * 获取SqlSession的方法
     */
    public static SqlSession getSession(){
        SqlSession session = tl.get();
        if(session==null){
            tl.set(factory.openSession());
        }
        return tl.get();
    }
    
    public static void closeSession(){
        SqlSession session = tl.get();
        if(session!=null){
            session.close();
        }
        tl.set(null);
    }
}

 

拦截器:

import java.io.IOException;
import java.io.InputStream;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.bjsxt.util.MyBatisUtil;
/**
 * 最开始是由Spring框架提出的.整合Hibernate框架是使用的是OpenSessionInView
 * 
 * 
 * @author Administrator
 *
 */
@WebFilter("/*")
public class OpenSessionInView implements Filter{
    @Override
    public void init(FilterConfig filterconfig) throws ServletException {   
    }
    @Override
    public void doFilter(ServletRequest servletrequest, ServletResponse servletresponse, FilterChain filterchain)
            throws IOException, ServletException {  
        SqlSession session = MyBatisUtil.getSession();
        try {
            filterchain.doFilter(servletrequest, servletresponse);//允许servlet执行,而允许service执行
            session.commit();
        } catch (Exception e) {
            session.rollback();
            e.printStackTrace();
        }finally{
            MyBatisUtil.closeSession();
        }
    }
    @Override
    public void destroy() {
    }
}

缓存

MyBatis 中默认 SqlSession 缓存开启

SqlSession 缓存必须是同一个SqlSession 对象

同一个 SqlSession 对象调用同一个时,只有第一次访问数据库,第一次之后把查询结果缓存到 SqlSession 缓存区(内存)中

缓存流程

步骤一: 先去缓存区中找是否存在 statement(<select>) 步骤二:返回结果 步骤三:如果没有缓存 statement 对象,去数据库获取数据 步骤四:数据库返回查询结果 步骤五:把查询结果放到对应的缓存区中

SqlSessionFactory 缓存

比 SqlSession 缓存高一级的二级缓存,默认关闭 开启方法再mapper.xml的mapper中添加标签:

<mapper namespace="com.bjsxt.mapper.LogMapper">
<cache readOnly="true"></cache>
    <insert id="ins" parameterType="log">
        insert into log values(default,#{accOut},#{accIn},#{money})
    </insert>
</mapper>

只有当SqlSession在commit()或close()的时候才会将SqlSession缓存提交到SqlSessionFactory缓存中

Mybatis运行原理

运行过程中需要用到的类:

Resource 加载Mybatis全局配置文件的IO流工具

SqlSessionFactoryBuilder() 创建SqlSessionFactory接口的实现类

XMLConfigBuilder 读取全局配置文件的流内容,转换为JAVA代码

Configuration 由XMLConfigBuilder 创建,封装了全局配置文件中所有的属性信息

DefaultSqlSessionFactory 是SqlSessionFactory接口的实现类

Transaction 事务类 每一个Session都会创建一个Transaction对象进行事务管理

TransactionFactory 事务工厂,负责生产事务类

Executor Mybatis执行器 一般使用SimpleExecutor实现类,批量操作时,使用BatchExecutor 通过OpenSession的参数控制 负责执行SQL命令 相当于JDBC 中的statement对象或preparedStatement对象或callableStatement对象

Mybatis结束

posted @ 2019-08-09 10:51  夏了夏天丶  阅读(315)  评论(0编辑  收藏  举报